#!/usr/bin/env python
""" AnyBackup is a windows specific backup program to keep multiple volumes in sync with multiple volumes
    Copyright (C) 2011  Andrew Hopkinson

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    Exported Classes:

    listdialog -- a custom dialog which allows a user to provide regular expressions for file extensions to include filenames to exclude.
    """
import wx
import wx.lib.agw.aui as aui
import re

class remoteDialog(wx.Dialog):
    def __init__(self,parent,driveRef):
        self._drive = driveRef
        self._host = driveRef.getRemoteHost()
        self._path = driveRef.getRemotePath()
        label = '%s - Remote Index'%driveRef.getName()
        wx.Dialog.__init__(self,parent,-1,label,wx.DefaultPosition,wx.Size(200,135))
        hostStr = ''
        pathStr = ''
        if self._drive.getRemoteHost():
            hostStr = self._drive.getRemoteHost()
        if self._drive.getRemotePath():
            pathStr = self._drive.getRemotePath()
        hostPanel = wx.Panel(self, -1)
        pathPanel = wx.Panel(self, -1)
        buttonPanel = wx.Panel(self, -1)
        mainBox = wx.BoxSizer(wx.VERTICAL)
        hostBox = wx.BoxSizer(wx.HORIZONTAL)
        pathBox = wx.BoxSizer(wx.HORIZONTAL)
        buttonBox = wx.BoxSizer(wx.HORIZONTAL)
        self.hostCtrl = wx.TextCtrl(hostPanel, -1, hostStr, wx.DefaultPosition)
        self.pathCtrl = wx.TextCtrl(pathPanel, -1, pathStr, wx.DefaultPosition)
        self.hostLabel = wx.StaticText(hostPanel,-1,'Remote Host',wx.DefaultPosition)
        self.pathLabel = wx.StaticText(pathPanel,-1,'Remote Path',wx.DefaultPosition)
        self.save = wx.Button(buttonPanel,-1,"Save")
        self.cancel = wx.Button(buttonPanel,-1,"Cancel")
        hostBox.Add(self.hostLabel,0,wx.ALL,5)
        hostBox.Add(self.hostCtrl,0,wx.ALL,5)
        pathBox.Add(self.pathLabel,0,wx.ALL,5)
        pathBox.Add(self.pathCtrl,0,wx.ALL,5)
        buttonBox.Add(self.save,0,wx.LEFT,5)
        buttonBox.Add(self.cancel)
        hostPanel.SetSizer(hostBox)
        pathPanel.SetSizer(pathBox)
        buttonPanel.SetSizer(buttonBox)
        mainBox.Add(hostPanel,0)
        mainBox.Add(pathPanel,0)
        mainBox.Add(buttonPanel,0)
        self.SetSizer(mainBox)
        self.save.Bind(wx.EVT_BUTTON,self.saveRemote)
        self.cancel.Bind(wx.EVT_BUTTON,self.closeDialog)
        
    def saveRemote(self,evt):
        self._drive.setRemoteHost(self.hostCtrl.GetValue())
        self._drive.setRemotePath(self.pathCtrl.GetValue())
        self.Close(1)
        
    def closeDialog(self,evt):
        self.Close(1)

class manageDirDialog(wx.Dialog):
    def __init__(self,parent,driveRef):
        self._drive = driveRef
        self._dirList = self._drive.getDirList()
        label = '%s - Directories'%driveRef.getName()
        wx.Dialog.__init__(self,parent,-1,label,wx.DefaultPosition,wx.Size(250,350))
        self.mgr = aui.AuiManager(self)
        self.dirBox = wx.ListBox(self,-1,style=wx.LB_EXTENDED)
        for directory in self._dirList:
            self.dirBox.Insert(str(directory),0,None)
        buttonPanel = wx.Panel(self,-1,size=(-1,32))
        addDir = wx.Button(buttonPanel,-1,'Add...')
        removeDir = wx.Button(buttonPanel,-1,'Remove')
        buttonBox = wx.BoxSizer(wx.HORIZONTAL)
        buttonBox.Add(addDir,0,wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.TOP,5)
        buttonBox.Add(removeDir,0,wx.BOTTOM|wx.RIGHT|wx.TOP,5)
        buttonPanel.SetSizer(buttonBox)
        self.mgr.AddPane(self.dirBox,aui.AuiPaneInfo().Name('Directories').Floatable(False).Caption('Directories').Gripper(False).Center().CloseButton(False))
        self.mgr.AddPane(buttonPanel,aui.AuiPaneInfo().Name('Buttons').Gripper(False).CaptionVisible(False).Bottom().CloseButton(False))
        self.mgr.Update()
        self.Bind(wx.EVT_BUTTON,self.removeDir,removeDir)
        self.Bind(wx.EVT_BUTTON,self.addDir,addDir)
        
    def removeDir(self,evt):
        remove = self.dirBox.GetSelections()
        selectList = self._dirList[:]
        selectList.reverse()
        for index in remove:
            self._drive.removeDir(selectList[index])
        self._dirList = self._drive.getDirList()
        self.changeList(evt)
    
    def addDir(self,evt):
        dialog = wx.DirDialog(self,message='Pick a directory to index.')
        if dialog.ShowModal() == wx.ID_OK:
            if self._drive.owns(dialog.GetPath()):
                result = self._drive.addDir(dialog.GetPath())
                if not result:
                    error = wx.MessageDialog(self,'Error Adding Dir, is it a subdir of an already added directory?','Add Error', wx.OK | wx.ICON_ERROR)
                    error.ShowModal()
                elif result == self._drive.OVERWRITE:
                    warn = wx.MessageDialog(self,'The directory added contained one or more of the subdirectories already present, sub dirs removed.','Overwrote Subdir(s)', wx.OK | wx.ICON_WARNING)
                    warn.ShowModal()
                    self.changeList(evt)
                else:
                    self.changeList(evt)
        
    def changeList(self,event):
        """ populates the listbox with the skip list of the valid extension list depending on whath as been selected """
        self.dirBox.Clear()
        for item in self._dirList:
            self.dirBox.Insert(item,0,None)

class listdialog(wx.Dialog):
    """ a custom dialog which allows a user to provide regular expressions for file extensions to include filenames to exclude.
    Public functions:
    close -- closes the dialog"""

    def __init__(self,parent,buManager):
        self.buObject = buManager
        skipList = buManager.getSkipList()
        extList = buManager.getValidExt()
        label = "Extensions and Skiplist Management"
        wx.Dialog.__init__(self,parent,-1,label,wx.DefaultPosition,wx.Size(250,350))
        listSelPanel = wx.Panel(self)
        buttonPanel = wx.Panel(self)
        listSelBox = wx.BoxSizer(wx.HORIZONTAL)
        buttonBox = wx.BoxSizer(wx.HORIZONTAL)
        mainBox = wx.BoxSizer(wx.VERTICAL)
        self.ids = {}
        self.ids['listLabel']=1
        self.ids['listSelect']=2
        self.ids['listBox']=3
        self.ids['add']=4
        self.ids['remove']=5
        self.ids['cancel']=6
        self.listLabel = wx.StaticText(listSelPanel,self.ids['listLabel'],"List")
        self.listSelect = wx.ComboBox(listSelPanel,self.ids['listSelect'],"Skip",wx.DefaultPosition,wx.DefaultSize,['Skip','Valid Ext'])
        self.listBox = wx.ListBox(self,self.ids['listBox'],style=wx.LB_EXTENDED)
        self.add = wx.Button(buttonPanel,self.ids['add'],"Add")
        self.remove = wx.Button(buttonPanel,self.ids['remove'],"Remove")
        self.cancel = wx.Button(buttonPanel,self.ids['cancel'],"Close")
        listSelBox.Add(self.listLabel,0,wx.LEFT|wx.TOP|wx.RIGHT,8)
        listSelBox.Add(self.listSelect,0,wx.TOP|wx.RIGHT,5)
        listSelPanel.SetSizer(listSelBox)
        buttonBox.Add(self.add,0,wx.LEFT|wx.RIGHT|wx.BOTTOM,5)
        buttonBox.Add(self.remove,0,wx.BOTTOM|wx.RIGHT,5)
        buttonBox.Add(self.cancel,0,wx.BOTTOM|wx.RIGHT,5)
        buttonPanel.SetSizer(buttonBox)
        mainBox.Add(listSelPanel,0)
        mainBox.Add(self.listBox,1,wx.ALL|wx.EXPAND,5)
        mainBox.Add(buttonPanel,0)
        self.SetSizer(mainBox)
        wx.EVT_BUTTON(self,self.ids['add'],self.addStr)
        wx.EVT_BUTTON(self,self.ids['remove'],self.removeStr)
        wx.EVT_BUTTON(self,self.ids['cancel'],self.close)
        wx.EVT_COMBOBOX(self,self.ids['listSelect'],self.changeList)
        for skip in skipList:
            self.listBox.Insert(skip,0,None)

    def close(self,event):
        """ closes the dialog """
        self.Close(1)

    def addStr(self,event):
        """ promps for a regular expression and adds it to the skip list or the valid extension list """
        dialog = wx.TextEntryDialog(self,"Enter new "+self.listSelect.GetValue(),"Add "+self.listSelect.GetValue(),"",style=wx.OK|wx.CANCEL)
        if dialog.ShowModal() == wx.ID_CANCEL:
            return
        else:
            add = dialog.GetValue()
            try:
                # A naive regular expression validator -- the assumption being that if the regex is invalid an exception will be thrown
                re.search(add,'test')
            except:
                wx.MessageDialog(self,'The regular expression you entered is invalid.','Invalid Regex!', wx.OK|wx.ICON_ERROR).ShowModal()
            else:
                if re.search("skip",self.listSelect.GetValue(),re.IGNORECASE):
                    self.buObject.addSkip(add)
                else:
                    self.buObject.addValidExt(add)
                self.changeList(event)

    def getList(self):
        """ returns the current skip list or valid extension list """
        list = []
        if re.search("skip",self.listSelect.GetValue(),re.IGNORECASE):
            list = self.buObject.getSkipList()
        else:
            list = self.buObject.getValidExt()
        return list

    def removeStr(self,event):
        """ removes a given string from the skip lits or the valid extension list """
        remove = self.listBox.GetSelections()
        list = self.getList()
        for index in sorted(remove, reverse=True):
            del list[index]
        if re.search("skip",self.listSelect.GetValue(),re.IGNORECASE):
            self.buObject.setSkipList(list)
        else:
            self.buObject.setValidExt(list)
        self.changeList(event)

    def changeList(self,event):
        """ populates the listbox with the skip list of the valid extension list depending on whath as been selected """
        list = self.getList()
        self.listBox.Clear()
        for item in list:
            self.listBox.Insert(item,0,None)


